using System.Collections.Generic;
using System.Threading;

namespace Nice157Advices.Advices
{
    /// <summary>
    /// 22、确保集合的线性安全
    /// </summary>
    public static class _22
    {
        /*
            建议18中提到，foreach循环不能代替for循环的一个原因是在迭代过程中对集合本身进行了增删操作。将此场景移植到多线程场景中，就是本建议要阐述的重点：确保集合的线程安全。集合线程安全是指在多个线程上添加活删除元素时，线程之间必须保持同步。
         */

        public static void Go ()
        {
            var list = new List<Person> ()
            {
                new Person { Name = "capdiem", Age = 24 },
                new Person { Name = "lena", Age = 25 },
                new Person { Name = "fox", Age = 26 },
            };

            var syncObject = new object (); // 用于锁定，处理逻辑在同一组的线程要用同一锁定对象

            var autoSet = new AutoResetEvent (false);

            Thread t1 = new Thread (() =>
            {
                // 阻止当前线程
                autoSet.WaitOne ();
                lock (syncObject)
                {
                    foreach (var item in list)
                    {
                        System.Console.WriteLine ($"t1: {item.Name}");
                        Thread.Sleep (1000);
                    }
                }
            });
            t1.Start ();

            Thread t2 = new Thread (() =>
            {
                // 通知t1可以执行代码
                autoSet.Set ();
                Thread.Sleep (1000);
                lock (syncObject)
                {
                    list.RemoveAt (2);
                    System.Console.WriteLine("after removed at 2:");
                    foreach (var item in list) {
                        System.Console.Write("list: "+ item.Name + " ");
                    }
                }
            });
            t2.Start ();
        }

        private class Person
        {
            public string Name { get; set; }
            public int Age { get; set; }
        }
    }
}